---
description: Learn the different types and options available in Triplit schemas.
---

import { Callout } from 'nextra-theme-docs';

# Data types

When using a schema you have a few datatypes at your disposal:

### Collections and Schema types

The `Collections` and `Schema` schema types are used to define your collections and their attributes. They are simple record types but will help provide type hinting and validation to their parameters.

```typescript
import { Schema as S } from '@triplit/client';
const schema = S.Collections({
  todos: {
    schema: S.Schema({
      id: S.Id(),
      // Additional attributes here...
    }),
  },
});
```

### Primitive types

Primitive types are basic types for the database.

#### Id

The Id data type is a convenience String type used for entity identifiers. It automatically generates unique IDs when entities are inserted without an explicit `id` value.

```typescript
import { Schema as S } from '@triplit/client';
const idType = S.Id({
  format: 'nanoid', // or 'uuidv4' or 'uuidv7'
});
```

Valid options for the Id type include:

- `format`: Specifies the ID generation format. Options are:
  - `'nanoid'` (default): Generates a 21-character URL-safe ID using nanoid. Pre-installed on both client and server.
  - `'uuidv4'`: Generates a standard UUID v4. Uses native functionality, no additional package required.
  - `'uuidv7'`: Generates a UUID v7 with timestamp ordering. Requires the `uuidv7` package on the client (pre-installed on server).

```typescript
// Examples of different ID formats
const schema = S.Collections({
  todos: {
    schema: S.Schema({
      id: S.Id(), // defaults to nanoid
      text: S.String(),
    }),
  },
  users: {
    schema: S.Schema({
      id: S.Id({ format: 'uuidv4' }),
      name: S.String(),
    }),
  },
  posts: {
    schema: S.Schema({
      id: S.Id({ format: 'uuidv7' }),
      title: S.String(),
    }),
  },
});
```

<Callout type="info">
  For `uuidv7` format, install the package on the client: e.g. `npm install
  uuidv7`
</Callout>

#### String

The string data type is used to store text.

```typescript
import { Schema as S } from '@triplit/client';
const stringType = S.String({
  // options
});
```

Valid options for the string type include:

- `nullable`: Indicates the value is optional when used in a `Record`. This is equivalent to wrapping the attribute in [`S.Optional`](#optional-keys).
- `default`: Provides a default value or function for the attribute. Possible values include:
  - `S.Default.Id.nanoid()`: Generates a nanoid (21-character URL-safe ID)
  - `S.Default.Id.uuidv4()`: Generates a UUID v4
  - `S.Default.Id.uuidv7()`: Generates a UUID v7 (requires `uuidv7` package on client)
  - `string`: A literal string value.
- `enum`: An array of strings that restricts the possible values of the attribute. This will perform runtime validation and provide autocomplete in your editor.

For information about operators that can be used with strings in `where` statements, see the [Where clause documentation](/query/where#operators).

#### Number

The number data type is used to store integer or float numbers.

```typescript
import { Schema as S } from '@triplit/client';
const numberType = S.Number({
  // options
});
```

Valid options for the number type include:

- `nullable`: Indicates the value is optional when used in a `Record`. This is equivalent to wrapping the attribute in [`S.Optional`](#optional-keys).
- `default`: Provides a default value or function for the attribute. Possible values include:
  - `number`: A literal number value.

For information about operators that can be used with numbers in `where` statements, see the [Where clause documentation](/query/where#operators).

#### Boolean

The boolean data type is used to store true or false values.

```typescript
import { Schema as S } from '@triplit/client';
const booleanType = S.Boolean({
  // options
});
```

Valid options for the boolean type include:

- `nullable`: Indicates the value is optional when used in a `Record`. This is equivalent to wrapping the attribute in [`S.Optional`](#optional-keys).
- `default`: Provides a default value or function for the attribute. Possible values include:
  - `boolean`: A literal boolean value.

For information about operators that can be used with booleans in `where` statements, see the [Where clause documentation](/query/where#operators).

#### Date

The date data type is used to store date and time values.

```typescript
import { Schema as S } from '@triplit/client';
const dateType = S.Date({
  // options
});
```

Valid options for the date type include:

- `nullable`: Indicates the value is optional when used in a `Record`. This is equivalent to wrapping the attribute in [`S.Optional`](#optional-keys).
- `default`: Provides a default value or function for the attribute. Possible values include:
  - `S.Default.now()`: Generates the current date and time.
  - `string`: An ISO 8601 formatted string.

For information about operators that can be used with dates in `where` statements, see the [Where clause documentation](/query/where#operators).

### Set

Set types are used to store a collection of non nullable value types. Sets are unordered and do not allow duplicate values.

<Callout type="info" emoji="ℹ️">
  Lists, which support ordering and duplicate values, are on the
  [roadmap](https://triplit.dev/roadmap).
</Callout>

```typescript
import { Schema as S } from '@triplit/client';
const stringSet = S.Set(S.String(), {
  // options
});
```

The first argument to the `Set` constructor is the type of the values in the set. This can be any of the primitive types, including `S.String()`, `S.Number()`, `S.Boolean()`, or `S.Date()`.

Valid options for the set type include:

- `nullable`: Indicates the value is optional when used in a `Record`. This is equivalent to wrapping the attribute in [`S.Optional`](#optional-keys).
- `default`: Provides a default value or function for the attribute. Possible values include:
  - `S.Default.Set.empty()`: Generates an empty set.

For information about operators that can be used with sets in `where` statements, see the [Where clause documentation](/query/where#operators).

### Record

The record types allow you model nested information with known keys, similar to a struct in C.

```typescript
import { Schema as S } from '@triplit/client';
const recordType = S.Record(
  {
    street: S.String(),
    city: S.String(),
    state: S.String(),
    zip: S.String(),
  },
  {
    // options
  }
);
```

The first argument to the `Record` constructor is an object that defines the keys and their types. This can be any data type.

Valid options for the record type include:

- `nullable`: Indicates the value is optional when used in a `Record`. This is equivalent to wrapping the attribute in [`S.Optional`](#optional-keys).

For information about operators that can be used with records in `where` statements, see the [Where clause documentation](/query/where#operators).

#### Optional keys

You can indicate an attribute is optional by passing the `{ nullable: true }` option to its constructor or wrapping the attribute in `S.Optional`. Optional attributes may not exist, have the value `undefined`, or have the value `null` - these are all equivalent in Triplit.

Under the hood `S.Schema()` is a record type, so optional attributes allow you to define optional keys in your schema as well.

```typescript
import { Schema as S } from '@triplit/client';
const schema = S.Collections({
  test: {
    schema: S.Schema({
      id: S.Id(),
      // S.Optional and nullable are equivalent
      optionalString: S.Optional(S.String()),
      alsoOptionalString: S.String({ nullable: true }),
    }),
  },
});

await client.insert('test', {
  id: '123',
});

// { id: '123' }

await client.update('test', '123', (e) => {
  e.optionalString = 'hello';
});

// { id: '123', optionalString: 'hello' }

await client.update('test', '123', (e) => {
  delete e.optionalString;
});

// { id: '123', optionalString: null }
```

For information about operators that can be used with optional attributes in `where` statements, see the [Where clause documentation](/query/where#operators).

### Json

The json type is used to store arbitrary JSON data that is [spec](https://datatracker.ietf.org/doc/html/rfc7159) compliant. This type is useful for storing unstructured data or data that may change frequently.

Valid primitive types for the json type include:

- `string`
- `number`
- `boolean`
- `null`

You may also store arrays and objects containing any of the above types.

```typescript
import { Schema as S } from '@triplit/client';
const jsonType = S.Json({
  // options
});
```

Valid options for the json type include:

- `nullable`: Indicates the value is optional when used in a `Record`. This is equivalent to wrapping the attribute in [`S.Optional`](#optional-keys).
- `default`: Provides a default value or function for the attribute. Possible values include:
  - `json`: A literal JSON value.
  - Any default value for the primitive types that are JSON compliant.
